package org.example.nio;


import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

//nio服务端
/*
* 核心是 有个监听器专门的维护 是否可处理 的信息 这样就不避免了 空等阻塞  适用于 io密集型
* */
public class NioServer {
    public static void main(String[] args) throws IOException {
        Selector  selector = Selector.open();//监听器
        ServerSocketChannel ssc = ServerSocketChannel.open();
        ssc.bind(new InetSocketAddress("localhost", 8081));
        ssc.configureBlocking(false);//设置非阻塞模式

        ssc.register(selector, SelectionKey.OP_ACCEPT);//这个大channel 注册到监听器上 监听accept事件
        while (true) {
            selector.select();//监听事件 没有时会阻塞
            //遍历监听到的事件 即小 channel
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                SelectionKey key = iterator.next();
                iterator.remove();
                //大channel 有accept事件
                if (key.isAcceptable()) {
                    //拿到大channel
                    ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();
                    //实际的那一个客户端连接 小channel
                    SocketChannel socketChannel = serverSocketChannel.accept();

                    //把小channel 注册到监听器上 监听read事件  套娃
                    socketChannel.configureBlocking(false);
                    socketChannel.register(selector, SelectionKey.OP_READ);
                }
                //小channel 有read事件  关键在这里 能read才read  可以直接返回
                if (key.isReadable()) {
                    //拿到小channel
                    SocketChannel socketChannel = (SocketChannel) key.channel();
                    //从小channel 读数据
                    ByteBuffer byteBuffer = ByteBuffer.allocate(12);

                    //读取直接返回 不需要阻塞
                    int length = socketChannel.read(byteBuffer);
                    //为-1 说明客户端断开链接了 服务端也断开连接
                    if  (length == -1) {
                        socketChannel.close();
                    }
                    //真正的处理数据的逻辑
                    else {
                        byteBuffer.flip();
                        byte[] buffer = new byte[byteBuffer.remaining()];
                        byteBuffer.get(buffer);
                        String message = new String(buffer);
                        System.out.println(message);

                    }
                }


            }

        }



    }


}